package com.example.androidproject;

import android.content.Context;
import android.content.res.Configuration;

import androidx.annotation.NonNull;
import androidx.multidex.MultiDexApplication;

import com.alibaba.sdk.android.oss.ClientConfiguration;
import com.alibaba.sdk.android.oss.OSS;
import com.alibaba.sdk.android.oss.OSSClient;
import com.alibaba.sdk.android.oss.common.OSSLog;
import com.alibaba.sdk.android.oss.common.auth.OSSCredentialProvider;
import com.alibaba.sdk.android.oss.common.auth.OSSPlainTextAKSKCredentialProvider;
import com.example.androidproject.api.UserInfoImpl;
import com.example.androidproject.data.Config;
import com.hyg.base.BaseLibrary;
import com.hyg.common.utils.AppUtils;
import com.hyg.common.utils.CrashHandler;
import com.hyg.common.utils.LogManager;
import com.hyg.common.utils.LogUtils;
import com.hyg.common.utils.language.LocalManageUtil;
import com.hyg.common.utils.language.SPLanguageUtil;
import com.hyg.idea.api.ApiInterface;
import com.tencent.bugly.crashreport.CrashReport;

import java.io.IOException;
import java.net.SocketException;

import io.reactivex.exceptions.UndeliverableException;
import io.reactivex.functions.Consumer;
import io.reactivex.plugins.RxJavaPlugins;


public class MyApp extends MultiDexApplication implements CrashHandler.OnCrashListener {
    private final String TAG = "MyApp";

    private static MyApp mApp;

    public static OSS oss;

    public  static MyApp getApp() {
        return mApp;
    }

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        LocalManageUtil.onConfigurationChanged(getApplicationContext());
    }

    @Override
    protected void attachBaseContext(Context base) {
        //保存系统选择语言
        LocalManageUtil.saveSystemCurrentLanguage(base);
        super.attachBaseContext(base);
    }

    @Override
    public void onCreate() {
        super.onCreate();

        mApp = this;

        CrashHandler.getInstance().init(this).setOnCrashListener(this);
        //如果需要保存API日志到sd卡需要先初始化
        LogManager.getInstance().init(this);
        LogManager.getInstance().addLog("appVersion",String.format("versionCode = %s, versionName = %s\r\n",AppUtils.getAppVersionCode(this),AppUtils.getAppVersionName(this)));

        if(SPLanguageUtil.getInstance(this).getSelectLanguage() == -1){
            //默认简体中文
            LocalManageUtil.saveSelectLanguage(this, 0);
        }

        BaseLibrary.init(this);
        initBugly();
        initOSSConfig();
        initInterfaces();
        setRxJavaErrorHandler();
    }

    /**
     * 初始化腾讯bug管理平台
     */
    private void initBugly() {
        /* Bugly SDK初始化
         * 参数1：上下文对象
         * 参数2：APPID，平台注册时得到,注意替换成你的appId
         * 参数3：是否开启调试模式，调试模式下会输出'CrashReport'tag的日志
         * 注意：如果您之前使用过Bugly SDK，请将以下这句注释掉。
         */
        CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(getApplicationContext());
        strategy.setAppVersion(AppUtils.getAppVersionName(this));
        strategy.setAppPackageName(getPackageName());
        strategy.setAppReportDelay(20000);    //Bugly会在启动20s后联网同步数据

        /*  第三个参数为SDK调试模式开关，调试模式的行为特性如下：
            输出详细的Bugly SDK的Log；
            每一条Crash都会被立即上报；
            自定义日志将会在Logcat中输出。
            建议在测试阶段建议设置成true，发布时设置为false。*/
        CrashReport.initCrashReport(getApplicationContext(), "APPID", BuildConfig.DEBUG ,strategy);
//        CrashReport.putUserData(this, "userAccount", AppUserInfo.getInstance().getAccount());
//        CrashReport.setUserId(this,AppUserInfo.getInstance().getUserId());
    }

    private void initOSSConfig(){
        OSSCredentialProvider credentialProvider = new OSSPlainTextAKSKCredentialProvider(Config.accessKey, Config.screctKey);
        ClientConfiguration conf = new ClientConfiguration();
        conf.setConnectionTimeout(15 * 1000); // 连接超时，默认15秒
        conf.setSocketTimeout(15 * 1000); // socket超时，默认15秒
        conf.setMaxConcurrentRequest(5); // 最大并发请求书，默认5个
        conf.setMaxErrorRetry(2); // 失败后最大重试次数，默认2次
        if(BuildConfig.DEBUG){
            OSSLog.enableLog();
        }
        oss = new OSSClient(getApplicationContext(), Config.OSS_BUCKET_HOST_ID, credentialProvider, conf);
    }

    private void initInterfaces(){
        ApiInterface.getInstance().setUserInfoInterface(new UserInfoImpl());
    }

    private void setRxJavaErrorHandler(){
        RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
            @Override
            public void accept(Throwable e) {
                e.printStackTrace();
                if (e instanceof UndeliverableException) {
                    e = e.getCause();
                    LogUtils.d(TAG, "UndeliverableException=" + e.getMessage());
                    return;
                } else if ((e instanceof IOException || e instanceof SocketException)) {
                    // fine, irrelevant network problem or API that throws on cancellation
                    return;
                } else if (e instanceof InterruptedException) {
                    // fine, some blocking code was interrupted by a dispose call
                    return;
                } else if ((e instanceof NullPointerException) || (e instanceof IllegalArgumentException)) {
                    // that's likely a bug in the application
                    Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                    return;
                } else if (e instanceof IllegalStateException) {
                    // that's a bug in RxJava or in a custom operator
                    Thread.currentThread().getUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), e);
                    return;
                }
                LogUtils.d(TAG, "unknown exception=" + e);
            }
        });
    }

    @Override
    public void onCrash(Throwable ex) {

    }
}
